package com.leave.mos.service.impl;

import com.leave.mos.constant.TablenameConstant;
import com.leave.mos.entity.QueryParam;
import com.leave.mos.service.find.QueryAggregate1Service;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.ArrayOperators;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @ClassName QueryAggregateServiceImpl
 * @Description TODO
 * @Author lh
 * @Date 2021/7/9 16:50
 * @Version 1.0
 *      $addFields 输出包含输入文档中所有现有字段和新添加字段的文档. (所有 + 新的)
 *      $project   明确指定输入文档中所有现有字段并添加新字段的阶段。(指定现有的 + 新的)
 *
 *  聚合取值的方式
 **/
@Service
public class QueryAggregate1ServiceImpl implements QueryAggregate1Service {


    @Resource
    private MongoTemplate mongoTemplate;

    @Override
    public List<Map> project(QueryParam queryParam){

        Aggregation aggregation = Aggregation.newAggregation(
                //1. project 只查询文档中存在的字段的 这几个字段信息 ; 相当于 select userId,status,boxId from googs_order
                Aggregation.project("userId","status","boxId")
        );

        AggregationResults<Map> aggregate = mongoTemplate.aggregate(aggregation, TablenameConstant.goods_order.TableName, Map.class);
        List<Map> maps = aggregate.getMappedResults();

        return maps;
    }

    @Override
    public List<Map> addFields(QueryParam queryParam){

        List<String> list = new ArrayList<>();
        list.add("小明");
        list.add("小红");

        Aggregation aggregation = Aggregation.newAggregation(
                //1. addFields  输出文档字段 并且在文档中添加 boxPriceValue; 相当于 select * , boxPriceValue from googs_order
                //2. 如果添加的字段名字在文档中已经存在，则添加的字段对应的值，会覆盖现有字段的值;指定现有字段名称会导致替换原始字段。
                //3. 可以使用$ 获取字段的值 赋值给新加的字段
                //4. 可以用用$ 获取某一个字段的值 覆盖掉原有的字段值
                //5. 向数组添加元素
                //-- 5.1可以使用$addFields与一个$concatArrays 表达将元素添加到现有的阵列字段
                //-- 5.2可以使用$addFields与一个$concatArrays 表达将现有元素 赋值给这个新 阵列字段


                Aggregation.addFields()
                        .addField("boxPriceSum").withValue("boxPriceValue")
                        .addFieldWithValue("boxStandard","9*9*9")
                        .addFieldWithValue("sd","$orderCode")
                        .addFieldWithValue("_id","$orderName")
                        .addField("arrayAdd").withValue(ArrayOperators.ConcatArrays.arrayOf(list))
                       // .addField("arrayAdd2").withValue(ArrayOperators.ConcatArrays.arrayOf("$boxPrice"))

                        .build()
                //Aggregation.group("userId").count().as("countNum")
        );

        AggregationResults<Map> aggregate = mongoTemplate.aggregate(aggregation, TablenameConstant.goods_order.TableName, Map.class);
        List<Map> maps = aggregate.getMappedResults();

        return maps;
    }

    //将包含输入到该阶段的文档数量计数的文档传递到下一个阶段。
    @Override
    public List<Map> count(QueryParam queryParam){

        //上一个文档的数量
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(Criteria.where("userId").is(1)),
                Aggregation.count().as("userIdOrderCount")
        );

        AggregationResults<Map> aggregate = mongoTemplate.aggregate(aggregation, TablenameConstant.goods_order.TableName, Map.class);
        List<Map> maps = aggregate.getMappedResults();

        return maps;
    }


    //将包含输入到该阶段的文档数量计数的文档传递到下一个阶段。
    @Override
    public List<Map> group(QueryParam queryParam){

        //上一个文档的数量
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(Criteria.where("userId").is(1)),
                Aggregation.group("status")
                        // 分组内 总数量
                        .count().as("countNum")
                        //分组内 第一条数据的 orderName
                        .first("orderName").as("orderName")
                        //分组内 最后一条数据的id
                        .last("_id").as("ids")
                        //分组内 求和
                        .sum("boxUnitPrice").as("groupTotal")
                        //分组内 平均值
                        .avg("boxUnitPrice").as("groupAvg"),
                //输出字段排除 id
                Aggregation.project("_id","countNum","orderName","ids","groupTotal","groupAvg").andExclude("_id")
        );

        AggregationResults<Map> aggregate = mongoTemplate.aggregate(aggregation, TablenameConstant.goods_order.TableName, Map.class);
        List<Map> maps = aggregate.getMappedResults();

        return maps;
    }

    //分组 输出 组内的数据
    //将包含输入到该阶段的文档数量计数的文档传递到下一个阶段。
    @Override
    public List<Map> group1(QueryParam queryParam){

        //上一个文档的数量
        Aggregation aggregation = Aggregation.newAggregation(
                //Aggregation.match(Criteria.where("userId").is(1)),
                Aggregation.group("userId").last("userId").as("userId").push("orderCode").as("orderCodes"),
                //输出字段排除 id
                Aggregation.project("userId","orderCodes").andExclude("_id")
        );

        AggregationResults<Map> aggregate = mongoTemplate.aggregate(aggregation, TablenameConstant.goods_order.TableName, Map.class);
        List<Map> maps = aggregate.getMappedResults();

        return maps;
    }

    //分组 输出 组内的数据
    @Override
    public List<Map> group2(QueryParam queryParam){

        //上一个文档的数量
        Aggregation aggregation = Aggregation.newAggregation(
                //Aggregation.match(Criteria.where("userId").is(1)),
                Aggregation.group("userId")
                        //分组 使用分组字段
                        .first("userId").as("userId")
                        //数值的操作 使用push方法
                        .push("dest").as("dests").sum("dest.num").as("destsNumTotal"),
                //输出字段排除 id
                Aggregation.project("userId","dests","destsNumTotal").andExclude("_id")
        );
        AggregationResults<Map> aggregate = mongoTemplate.aggregate(aggregation, TablenameConstant.goods_order.TableName, Map.class);
        List<Map> maps = aggregate.getMappedResults();

        return maps;
    }

}
